#include "cem/assembler.h"
#include "cem/electromagnetics_system.h"
#include "cem/material_database.h"
#include "cem/mesh_manager.h"
#include "cem/parameter_reader.h"
#include "cem/post_processor.h"

#include <gtest/gtest.h>

#include <libmesh/libmesh.h>
#include <libmesh/linear_implicit_system.h>
#include <libmesh/numeric_vector.h>

#include <fstream>
#include <string>

using cem::Assembler;
using cem::ElectromagneticsSystem;
using cem::MaterialDatabase;
using cem::MeshManager;
using cem::ParameterReader;
using cem::PostProcessor;

static libMesh::LibMeshInit * g_libmesh_init = nullptr;

// 函数: build_minimal_system
// 作用: 构造一个最小系统，并清零解向量，便于快速进行 VTK 写出与日志测试
static void build_minimal_system(ElectromagneticsSystem & out_sys, MeshManager & out_mesh_mgr)
{
    ASSERT_NE(g_libmesh_init, nullptr);
    MeshManager mesh(g_libmesh_init->comm());
    mesh.prepare_empty_mesh();

    ParameterReader params;
    const std::string tmp_path = "./tmp_minimal_post_config.json";
    const std::string json_text = R"JSON({
        "FREQUENCY": [{"value": 1.0}],
        "PHYSICAL_AREA": {"EPSL": [], "COND": [], "MU": []}
    })JSON";
    {
        std::ofstream ofs(tmp_path);
        ofs << json_text;
    }
    ASSERT_TRUE(params.load_from_file(tmp_path));

    cem::MaterialDatabase material_db;
    cem::BoundaryConditionManager bc_mgr; // 空集合

    out_sys.initialize(params, mesh, material_db, bc_mgr);

    // 将 mesh 管理器返回给调用者以维持 Mesh 生命周期
    out_mesh_mgr = std::move(mesh);
}

// 用例: PostProcessor 的基础日志与 VTK 写出在空网格/零解上不抛出异常
TEST(PostProcessorTest, basic_log_and_vtk_write_zero_solution)
{
    ElectromagneticsSystem system;
    MeshManager mesh_mgr(g_libmesh_init->comm());
    mesh_mgr.prepare_empty_mesh();

    build_minimal_system(system, mesh_mgr);

    // 清零解向量，模拟零解
    auto & lin = system.linear_system();
    ASSERT_TRUE(lin.solution.get() != nullptr);
    lin.solution->zero();
    lin.solution->close();

    PostProcessor pp;
    ASSERT_NO_THROW(pp.write_basic_log(system));

    // 写 VTK 到临时文件
    const std::string vtk_path = "./ut_post_snapshot.vtu";
    ASSERT_NO_THROW(pp.write_vtk_snapshot(system, vtk_path));
}

int main(int argc, char ** argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    libMesh::LibMeshInit init(argc, argv);
    g_libmesh_init = &init;
    return RUN_ALL_TESTS();
}